package com.nana.framework.net
{
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	
	public class DataChannel extends EventDispatcher
	{
		public static const LOGIN_COMP:String = "loginComp";
		public static const ENTER_SCENE_COMP:String = "enterSceneComp";
		public static const UPDATE:String = "update";
		public static const CLOSE:String = "flash_socketClose";
		public static const PHP_ERROR:String = "phpError";
		public static const HTTP:String = "http";
		public static const SOCKET:String = "socket";
		public static const KEY:String = "inulw";
		public static const LOCK:String = "lock_";
		
		private var _waitComb:Boolean = false;
		private var _isLogin:Boolean = false;
		private var _protocol:String = "http";
		private var _httpurl:String = "";
		private var _httpDataFormat:String = "text";
		private var timer:Timer;
		private var socket:FSocket;
		private var preEnterData:Object;
		private var reEnterCount:uint = 0;
		private var enterStatus:Boolean = false;
		private var httpReauest:HTTPRequest;
		private var broadcastCMD:Object;
		private var _flashHeartBeatTimer:Timer;
		private var socketCount:int = 0;
		private var _pause:Boolean = false;
		private var cmd6List:Array;
		private var _initSend:Boolean = false;
		private var _sendList:Array;
		private var httpType:String = "?";
		public var proxyFlag:Boolean = true;
		private var _initComp:Boolean = false;
		private var _httpCompList:Array;
		private var _friendComp:Boolean = false;
		private var _mimdDic:Dictionary;
		private var cmd5List:Vector.<ByteArray>;
		private var cmd14List:Vector.<ByteArray>;
		private var cmd15List:Vector.<ByteArray>;
		private var cmdList:Object;
		private var _lockCmdList:Object;
		private var _lockDataEventList:Object;
		
		public function DataChannel(){
			this.broadcastCMD = {};
			this.cmd6List = [];
			this._sendList = [];
			this._httpCompList = [];
			this._mimdDic = new Dictionary();
			this.cmd5List = new Vector.<ByteArray>();
			this.cmd14List = new Vector.<ByteArray>();
			this.cmd15List = new Vector.<ByteArray>();
			this.cmdList = {};
			this._lockCmdList = {};
			this._lockDataEventList = {};
			super();
		}
		
		public function connect(_arg1:String, _arg2:String):void{
			this.socket = new FSocket();
			this.socket.addEventListener(SocketEvent.DATA_COMP, this.onData);
			this.socket.addEventListener(IOErrorEvent.IO_ERROR, this.ioError);
			this.socket.addEventListener(SocketEvent.SOCKET_CLOSE, this.onClose);
			this.socket.addEventListener(SocketEvent.TRACE_EVENT, this.traceEventHandler);
			this.socket.connectMulti(_arg1, _arg2);
		}
		
		private function traceEventHandler(_arg1:SocketEvent):void{
		}
		private function onData(_arg1:SocketEvent):void{
			var _local2:String;
			var _local4:Object;
			var _local5:String;
			var _local6:Object;
			Debug.log(((("StoC CMD:" + _arg1.cmd) + "  RES") + _arg1.res), "dataChannel");
			var _local3:ByteArray = _arg1.data;
			if ((_arg1.res >> 15) == 1){
				_local3.uncompress();
			};
			if (_arg1.cmd == CmdCollection.FLASH_HEART_BEAT){
			} else {
				if (_arg1.cmd == CmdCollection.FLASH_MESSAGE){
					if (_arg1.res == 76){
						_local3.uncompress();
					};
					_local3.position = 0;
					_local2 = _local3.readUTFBytes(_local3.length);
					Debug.log(("GET:" + _local2), "dataChannel");
					_local4 = JSON.decode(_local2);
					this.runMimdHttpCompHandler(_local4);
					for (_local5 in _local4) {
						this.dispatchEvent(new DataEvent(_local5, _local4[_local5], ""));
					};
				} else {
					if (_arg1.cmd == CmdCollection.FLASH_ONLINE_IDS){
						_local3.position = 0;
						_local2 = _local3.readUTFBytes(_local3.length);
						Debug.log(("GET:" + _local2), "dataChannel");
						_local6 = JSON.decode(_local2);
						this.dispatchEvent(new DataEvent("friendOnLineNotice", _local6, ""));
						this.startHeartBeat();
					} else {
						if (_arg1.cmd == CmdCollection.GAME_LOGIN){
						};
					};
				};
			};
		}
		private function heartBeatTimer(_arg1:TimerEvent):void{
			var _local2:ByteArray = new ByteArray();
			this.socket.send(CmdCollection.FLASH_HEART_BEAT, _local2);
		}
		public function startHeartBeat():void{
			if (!this._flashHeartBeatTimer){
				this._flashHeartBeatTimer = new Timer(30000);
				this._flashHeartBeatTimer.addEventListener(TimerEvent.TIMER, this.heartBeatTimer);
			};
			this._flashHeartBeatTimer.start();
		}
		public function stopHeartBeat():void{
			if (this._flashHeartBeatTimer){
				this._flashHeartBeatTimer.stop();
			};
		}
		private function ioError(_arg1:IOErrorEvent):void{
			Debug.log(_arg1, "dataChannel");
		}
		private function onClose(_arg1:Event):void{
			if (this.isLogin == false){
			};
			this._isLogin = false;
			this.enterStatus = false;
			Debug.log(("连接断开" + _arg1), "dataChannel");
			this.socketCount++;
			if (this.socketCount > 3){
				this.stopHeartBeat();
			};
		}
		public function get pause():Boolean{
			return (this._pause);
		}
		public function set pause(_arg1:Boolean):void{
			this._pause = _arg1;
			if (this.socket != null){
				this.socket.pause = _arg1;
			};
		}
		public function login(_arg1:String, _arg2:String):void{
			Debug.log("请求登陆", "dataChannel");
			var _local3:ByteArray = new ByteArray();
			var _local4:String = _arg1;
			_local3.writeShort(_local4.length);
			_local3.writeUTFBytes(_local4);
			_local3.writeUTFBytes(_arg2);
			this.socket.send(CmdCollection.GAME_LOGIN, _local3);
		}
		public function enter(_arg1:String, _arg2:int, _arg3:String, _arg4:Object=null):void{
			var _local6:Object;
			Debug.log(("请求进入场景" + _arg2), "dataChannel");
			var _local5:String = ("00000000000000000000" + _arg1).slice(-20);
			if (_arg4 != null){
				_local6 = _arg4;
			} else {
				_local6 = {};
			};
			_local6["cmd"] = _arg3;
			_local6["reconnect"] = 0;
			if (this.preEnterData == null){
				this.preEnterData = {};
			};
			this.preEnterData["data"] = _local6;
			this.preEnterData["room"] = _arg2;
			this.preEnterData["sUserid"] = _local5;
			var _local7:String = JSON.encode(_local6);
			var _local8:ByteArray = new ByteArray();
			_local8.writeUTFBytes(_local5);
			_local8.writeUTFBytes(_local7);
			this.cmd6List.push({
				jsonByteArray:_local8,
				room:_arg2,
				sUserid:_local5
			});
			this.cmd6ListFlush();
		}
		private function cmd6ListFlush():void{
			var _local1:Object;
			var _local2:String;
			var _local3:ByteArray;
			if (this.isLogin == true){
				if (this.cmd6List.length > 0){
					while (this.cmd6List.length > 0) {
						_local1 = this.cmd6List.shift();
						this.socket.send(CmdCollection.ENTER_GAME, _local1["jsonByteArray"], _local1["room"], _local1["sUserid"]);
					};
				} else {
					if (((!((this.preEnterData == null))) && ((this.reEnterCount < 4)))){
						this.reEnterCount = (this.reEnterCount + 1);
						this.preEnterData["data"]["reconnect"] = 1;
						_local2 = JSON.encode(this.preEnterData["data"]);
						_local3 = new ByteArray();
						_local3.writeUTFBytes(this.preEnterData["sUserid"]);
						_local3.writeUTFBytes(_local2);
						this.socket.send(CmdCollection.ENTER_GAME, _local3, this.preEnterData["room"], this.preEnterData["sUserid"]);
					};
				};
			} else {
				this.socket.reConnect();
			};
		}
		public function send(_arg1:String, _arg2:Object=null, _arg3:Object=null):void{
			Debug.log(((("send..........." + _arg1) + JSON.encode(_arg2)) + JSON.encode(_arg3)), "dataChannel");
			if (this.protocol == DataChannel.HTTP){
				this.httpSend(_arg1, _arg2, _arg3);
			} else {
				if (this.protocol == DataChannel.SOCKET){
					this.socketSend(_arg1, _arg2);
				};
			};
		}
		public function socketSend(_arg1:String, _arg2:Object=null):void{
			var _local3:Object;
			if (_arg2 != null){
				_local3 = _arg2;
			} else {
				_local3 = {};
			};
			_local3["cmd"] = _arg1;
			var _local4:String = JSON.encode(_local3);
			Debug.log(("send:" + _local4), "dataChannel");
			var _local5:ByteArray = new ByteArray();
			_local5.writeUTFBytes(_local4);
			this.cmd5List.push(_local5);
			this.cmd5ListFlush();
		}
		public function httpSend(_arg1:String, _arg2:Object=null, _arg3:Object=null):void{
			if (_arg1 == "Scene.init"){
				this.httpSendHandler(_arg1, _arg2, _arg3);
			} else {
				if (this._initSend == false){
					this._sendList.push([_arg1, _arg2, _arg3]);
				} else {
					this.httpSendHandler(_arg1, _arg2, _arg3);
				};
			};
		}
		private function delaySend():void{
			var _local1:Array;
			this._initSend = true;
			while (this._sendList.length > 0) {
				_local1 = this._sendList.shift();
				this.httpSendHandler(_local1[0], _local1[1], _local1[2]);
			};
		}
		private function httpSendHandler(_arg1:String, _arg2:Object=null, _arg3:Object=null):void{
			var _local6:String;
			if (this.httpReauest == null){
				this.httpReauest = HTTPRequest.getInstance();
				this.httpReauest.httpUrl = this.httpurl;
				if (this.httpurl.indexOf("?") == -1){
					this.httpType = "";
				} else {
					this.httpType = "?";
				};
			};
			var _local4:String = JSON.encode(_arg2);
			var _local5:Object = {data:_local4};
			if (_arg3 != null){
				for (_local6 in _arg3) {
					_local5[_local6] = _arg3[_local6];
				};
			};
			if (this.httpType == ""){
				this.httpReauest.postRequest(("?method=" + _arg1), _local5, this.httpCompHandler, 60000, false, this.httpDataFormat, _arg1);
			} else {
				this.httpReauest.postRequest(_arg1, _local5, this.httpCompHandler, 60000, false, this.httpDataFormat, _arg1);
			};
		}
		public function httpSendForUrl(_arg1:String, _arg2:Object=null):void{
			if (this.httpReauest == null){
				this.httpReauest = HTTPRequest.getInstance();
				this.httpReauest.httpUrl = this.httpurl;
			};
			this.httpReauest.postRequest(_arg1, {data:_arg2}, this.httpCompHandler, 60000, false, "text", _arg1);
		}
		private function createHTTPRequest():HTTPRequest{
			if (this.httpReauest != null){
				return (this.httpReauest);
			};
			this.httpReauest = HTTPRequest.getInstance();
			this.httpReauest.httpUrl = this.httpurl;
			return (this.httpReauest);
		}
		public function resetSceneInit():void{
			this._initComp = false;
			this._friendComp = false;
			this._httpCompList.length = 0;
		}
		protected function httpCompHandler(_arg1:String, _arg2:Object=null):void{
			var _local3:Array;
			Debug.log(((("res....." + _arg2) + "-----------") + _arg1), "dataChannel");
			if (_arg2 == "Scene.init"){
				this.runHttpCompHandler(_arg1, _arg2);
				this._initComp = true;
				this.delaySend();
				if (this._friendComp == false){
					return;
				};
			} else {
				if ((((_arg2 == "Friend.run")) || ((_arg2 == "Friend.getGameData")))){
					this._friendComp = true;
					this._httpCompList.unshift([_arg1, _arg2]);
					if (this._initComp == false){
						return;
					};
				};
			};
			if ((((this._friendComp == true)) && ((this._initComp == true)))){
				while (this._httpCompList.length > 0) {
					_local3 = (this._httpCompList.shift() as Array);
					this.runHttpCompHandler(_local3[0], _local3[1]);
				};
				if (((!((_arg2 == "Friend.run"))) && (!((_arg2 == "Friend.getGameData"))))){
					this.runHttpCompHandler(_arg1, _arg2);
				};
			} else {
				this._httpCompList.push([_arg1, _arg2]);
			};
		}
		public function addMimdEventListener(_arg1:Array, _arg2:Function):void{
			if (!this._mimdDic[_arg1.join()]){
				this._mimdDic[_arg1.join()] = _arg2;
			};
		}
		public function removeMimdEventListener(_arg1:Array, _arg2:Function):void{
			if (this._mimdDic[_arg1.join()]){
				delete this._mimdDic[_arg1.join()];
			};
		}
		protected function runMimdHttpCompHandler(_arg1:Object):void{
			var _local2:Array;
			var _local3:Function;
			var _local4:int;
			var _local5:int;
			var _local6:String;
			var _local7:Object;
			var _local8:int;
			var _local9:String;
			for (_local6 in this._mimdDic) {
				_local7 = new Object();
				_local2 = _local6.split(",");
				_local3 = this._mimdDic[_local6];
				_local4 = _local2.length;
				_local5 = 0;
				_local8 = 0;
				while (_local8 < _local4) {
					_local9 = _local2[_local8];
					if (((!((_arg1 == null))) && (_arg1.hasOwnProperty(_local9)))){
						_local5++;
						_local7[_local9] = _arg1[_local9];
					};
					_local8++;
				};
				if (_local5 == _local4){
					_local3(_local7);
				};
			};
		}
		public function runHttpCompHandler(_arg1:String, _arg2:Object=null):void{
			var _local6:DataEvent;
			var _local7:Object;
			var _local8:String;
			var _local9:Object;
			var _local10:DataEvent;
			var _local3:RegExp = /\"(\d{18,})\"/g;
			var _local4:RegExp = /(\d{18,})/g;
			_arg1 = _arg1.replace(_local3, "$1");
			_arg1 = _arg1.replace(_local4, "\"$1\"");
			if (_arg1 == ""){
				return;
			};
			var _local5:Object = JSON.decode(_arg1);
			if (!_local5.hasOwnProperty("errorType")){
				if (_local5["result"] !== 0){
					_local5["method"] = String(_arg2);
					_local5["info"] = null;
					this.dispatchEvent(new DataEvent("phpError", _local5, ""));
				};
				_local6 = new DataEvent(_local5["method"], _local5, "");
				this.dispatchEvent(_local6);
				_local7 = _local5["info"];
				this.runMimdHttpCompHandler(_local7);
				if (_local7 != null){
					if (_arg2 == "Scene.init"){
						if (_local7.hasOwnProperty("time")){
							this.dispatchEvent(new DataEvent("time", _local7["time"], ""));
						};
						if (_local7.hasOwnProperty("player_info")){
							this.dispatchEvent(new DataEvent("player_info", _local7["player_info"], ""));
						};
						for (_local8 in _local7) {
							if (((!((_local8 == "time"))) || (!((_local8 == "player_info"))))){
								this.dispatchEvent(new DataEvent(_local8, _local7[_local8], ""));
							};
						};
					} else {
						for (_local8 in _local7) {
							this.dispatchEvent(new DataEvent(_local8, _local7[_local8], ""));
						};
					};
				};
			} else {
				if ((_arg2 is String)){
					_local9 = {};
					_local9["info"] = null;
					_local9["msg"] = _arg1;
					_local9["result"] = 1;
					_local9["method"] = String(_arg2);
					_local10 = new DataEvent(String(_arg2), _local9, "");
					this.dispatchEvent(_local10);
				};
				this.dispatchEvent(new DataEvent("dataError", _local5, ""));
			};
		}
		public function broadcast(_arg1:String, _arg2:Object=null):void{
			var _local3:Object;
			if (_arg2 != null){
				_local3 = _arg2;
			} else {
				_local3 = {};
			};
			_local3["cmd"] = _arg1;
			var _local4:String = JSON.encode(_local3);
			trace("broadcast:", _local4);
			var _local5:ByteArray = new ByteArray();
			_local5.writeUTFBytes(_local4);
			this.cmd15List.push(_local5);
			this.cmd15ListFlush();
		}
		private function cmd5ListFlush():void{
			var _local1:ByteArray;
			if (this.enterStatus == true){
				while (this.cmd5List.length > 0) {
					_local1 = this.cmd5List.shift();
					this.socket.send(5, _local1);
				};
			} else {
				this.socket.reConnect();
			};
		}
		private function cmd15ListFlush():void{
			if (this.enterStatus == true){
				while (this.cmd15List.length > 0) {
					this.socket.send(15, this.cmd15List.shift());
				};
			} else {
				this.socket.reConnect();
			};
		}
		public function broadcastData(_arg1:String, _arg2:String, _arg3:String, _arg4:Object, _arg5:Boolean=true):void{
			var _local6:Object = _arg4;
			_local6["broadcastCmd"] = _arg1;
			this.send("action", {
				descid:_arg2,
				sid:_arg3,
				data:_local6,
				exclusion:int(_arg5)
			});
		}
		public function toUser(_arg1:String, _arg2:Object):void{
			var _local3:String = ("00000000000000000000" + _arg1).slice(-20);
			var _local4:ByteArray = new ByteArray();
			_local4.writeUTFBytes(_local3);
			var _local5:String = JSON.encode(_arg2);
			_local4.writeUTFBytes(_local5);
		}
		public function updata(_arg1:Object):void{
			var _local2:Object;
			var _local3:Object;
			var _local4:String;
			var _local5:DataEvent;
			var _local6:DataEvent;
			if (_arg1.hasOwnProperty("cmd")){
				if (_arg1["cmd"] == "action"){
					_local2 = _arg1["data"];
					if ((_local2 is String)){
						_local4 = _arg1["data"];
						_local4 = _local4.replace(/\'/g, "\"");
						_local3 = JSON.decode(_local4);
					} else {
						_local3 = _local2;
					};
				} else {
					if (_arg1["cmd"] == "error"){
						_local5 = new DataEvent(DataEvent.ERROR_DATA, _arg1["data"], _arg1["key"]);
						this.dispatchEvent(_local5);
					} else {
						_local6 = new DataEvent(_arg1["cmd"], _arg1["data"], _arg1["key"]);
						this.dispatchEvent(_local6);
					};
				};
			};
		}
		override public function dispatchEvent(_arg1:Event):Boolean{
			var _local2:String;
			if ((_arg1 is DataEvent)){
				_local2 = (_arg1 as DataEvent).type;
				if (this._lockCmdList.hasOwnProperty(_local2)){
					if (!this._lockDataEventList.hasOwnProperty(_local2)){
						this._lockDataEventList[_local2] = [];
					};
					super.dispatchEvent((_arg1 as DataEvent).getNewDataEvent((LOCK + _arg1.type)));
					(this._lockDataEventList[_local2] as Array).push(_arg1);
					return (false);
				};
				return (super.dispatchEvent(_arg1));
			};
			return (super.dispatchEvent(_arg1));
		}
		public function lockCmd(_arg1:String):void{
			if (this._lockCmdList.hasOwnProperty(_arg1)){
				this._lockCmdList[_arg1] = (this._lockCmdList[_arg1] + 1);
			} else {
				this._lockCmdList[_arg1] = 1;
			};
		}
		public function unlockCmd(_arg1:String):void{
			var _local2:Array;
			if (this._lockCmdList.hasOwnProperty(_arg1)){
				this._lockCmdList[_arg1] = (this._lockCmdList[_arg1] - 1);
				if (this._lockCmdList[_arg1] <= 0){
					this._lockCmdList[_arg1] = 0;
					if (this._lockDataEventList.hasOwnProperty(_arg1)){
						_local2 = (this._lockDataEventList[_arg1] as Array);
						while (_local2.length > 0) {
							super.dispatchEvent((_local2.shift() as Event));
						};
					};
					delete this._lockCmdList[_arg1];
				};
			};
		}
		
		public function unlockCmdAll(_arg1:String):void{
			if (this._lockCmdList.hasOwnProperty(_arg1)){
				this._lockCmdList[_arg1] = 1;
				this.unlockCmd(_arg1);
			}
		}

		public function get waitComb():Boolean
		{
			return _waitComb;
		}

		public function get isLogin():Boolean
		{
			return _isLogin;
		}

		public function get protocol():String
		{
			return _protocol;
		}

		public function set protocol(value:String):void
		{
			_protocol = value;
		}

		public function get httpurl():String
		{
			return _httpurl;
		}

		public function set httpurl(value:String):void
		{
			_httpurl = value;
			if (this.httpurl.indexOf("?") == -1){
				this.httpType = "";
			} else {
				this.httpType = "?";
			}
			if (this.httpReauest != null){
				this.httpReauest.httpUrl = value;
			}
		}

		public function get httpDataFormat():String
		{
			return _httpDataFormat;
		}

		public function set httpDataFormat(value:String):void
		{
			_httpDataFormat = value;
		}


	}
}